package com.example.blogsystem.service.impl;

import com.example.blogsystem.constants.Constant;
import com.example.blogsystem.exception.UserException;
import com.example.blogsystem.mapper.UserMapper;
import com.example.blogsystem.model.dto.FindPasswordDto;
import com.example.blogsystem.model.dto.LoginDto;
import com.example.blogsystem.model.dto.RegisterDto;
import com.example.blogsystem.model.dto.UserInfoDto;
import com.example.blogsystem.model.entity.User;
import com.example.blogsystem.model.vo.CaptchaVo;
import com.example.blogsystem.model.vo.LoginVo;
import com.example.blogsystem.service.UserService;
import com.example.blogsystem.utils.EmailUtils;
import com.example.blogsystem.utils.JwtUtils;
import com.example.blogsystem.utils.SecurityUtils;
import com.example.blogsystem.utils.UploadFileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private ExecutorService executorServicePool = Executors.newFixedThreadPool(4);

    @Override
    public LoginVo login(LoginDto loginDto) {

        User user = userMapper.getUserByEmail(loginDto.getEmail());
        //查询用户是否存在
        if(user == null){
            throw new UserException("用户名或密码错误！");
        }
        //校验用户密码
        if(!SecurityUtils.verify(loginDto.getPassword(), user.getPassword())){
            throw new UserException("用户名或密码错误！");
        }
        //生成token
        Map<String, Object> claims = new HashMap<>();
        claims.put("email", user.getEmail());
        claims.put("userName", user.getUserName());
        String token = JwtUtils.genToken(claims);
        //构造返回结果
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        return loginVo;
    }

    @Override
    public CaptchaVo generateCaptcha(String email) {

        if(!EmailUtils.isValidEmail(email)){
            throw new UserException("邮箱格式输入错误！");
        }
        String codeKey = UUID.randomUUID().toString().replace("-", "");
        // 通过线程池是实现异步写入redis数据
        executorServicePool.submit(() -> {
            String codeValue = EmailUtils.sendCode(email);
            redisTemplate.opsForValue().set(Constant.CAPTCHA + codeKey, codeValue, 2, TimeUnit.MINUTES);
        });
        //构造对象并返回
        CaptchaVo captchaVo = new CaptchaVo();
        captchaVo.setCodeKey(codeKey);
        return captchaVo;
    }

    @Override
    public void register(RegisterDto registerDto) {
        //查询用户
        User user = userMapper.getUserByEmail(registerDto.getEmail());
        if(user != null){
            throw new UserException("用户已经被注册！");
        }
        //校验验证码
        checkCaptcha(registerDto.getCodeKey(), registerDto.getCaptcha());
        //添加用户
        String password = registerDto.getPassword();
        String md5Password = SecurityUtils.encrypt(password);
        userMapper.insertUser(registerDto.getUserName(), md5Password, registerDto.getEmail());

    }

    @Override
    public void findPassword(FindPasswordDto findPasswordDto) {
        User user = userMapper.getUserByEmail(findPasswordDto.getEmail());
        if(user == null){
            throw new UserException("用户未注册！");
        }
        //校验验证码
        checkCaptcha(findPasswordDto.getCodeKey(), findPasswordDto.getCaptcha());
        //更新用户
        String password = findPasswordDto.getPassword();
        String md5Password = SecurityUtils.encrypt(password);
        userMapper.updatePasswordByEmail(findPasswordDto.getEmail(), md5Password);
    }

    @Override
    public void updateUser(UserInfoDto userInfoDto) {
        String email = JwtUtils.getUserEmailFromToken(userInfoDto.getUserToken());
        if(email == null){
            throw new UserException("登录过期！");
        }
        // 处理头像上传
        String avatarPath = "head/" + UploadFileUtils.uploadFile(userInfoDto.getAvatarFile());
        if(!StringUtils.hasLength(avatarPath)){
            throw new UserException("头像文件上传失败！");
        }
        User user = userMapper.getUserByEmail(email);
        userMapper.updateUserInfo(avatarPath,user.getUserName(), user.getGithubUrl(), email);
    }

    private void checkCaptcha(String codeKey, String sendCode){
        String codeValue = redisTemplate.opsForValue().get(Constant.CAPTCHA + codeKey);
        if(codeValue == null){
            throw new UserException("验证码已失效！");
        }
        if(!sendCode.equals(codeValue)){
            throw new UserException("验证码不正确！");
        }
    }
}
